package com.woniuxy.moneyapp.app.controller;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniuxy.commons.exception.MyException;
import com.woniuxy.commons.util.*;
import com.woniuxy.moneyapp.app.controller.form.RechargeStateInfo;
import com.woniuxy.moneyapp.client.PayRecordClient;
import com.woniuxy.moneyapp.client.param.*;
import com.woniuxy.moneyapp.client.param.MyWalletToShow;
import com.woniuxy.moneyapp.client.param.PayRecordToShow;
import com.woniuxy.moneyapp.common.enums.PaymentRelated;
import com.woniuxy.moneyapp.common.enums.SchemaCode;
import com.woniuxy.moneyapp.common.exception.code.FundExceptionCode;
import com.woniuxy.moneyapp.common.utils.CommonUtil;
import com.woniuxy.moneyapp.infra.dto.*;
import com.woniuxy.moneyapp.infra.dto.BalancePayDto;
import com.woniuxy.moneyapp.infra.model.PayRecord;
import com.woniuxy.moneyapp.service.PayRecordService;
import com.woniuxy.ptapp.client.ClassesOrderClient;
import com.woniuxy.ptapp.client.param.ClassesOrderDto;
import com.woniuxy.userapp.client.FrontAccountClient;
import com.woniuxy.userapp.client.StudentClient;
import com.woniuxy.userapp.client.VenueClient;
import com.woniuxy.userapp.client.param.ChangeAccountMoneyInfo;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.SneakyThrows;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author seven
 * @since 2022-08-01
 */
@RestController
public class PayRecordController implements PayRecordClient {

    @Resource
    private RocketMQTemplate rt;

    @Resource
    private PayRecordService payRecordService;

    @Resource
    private FrontAccountClient userClient;

    @Resource
    private StudentClient sc;

    @Resource
    private VenueClient vc;

    @Resource
    private ClassesOrderClient coc;

    @Resource
    private StringRedisTemplate srt;


    @SneakyThrows
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)
    public Result balancePay(BalancePayForm bp) {

        //根据token 查用户id 用户名
        LoginUserDto userDto = GetTokenUserLogin.getTokenUserLogin();
        //前台帐户id
        Integer uid = userDto.getLoginId();
        //Integer uid = 1;
        //前台帐户用户名
        String userName = userDto.getLoginName();
        //String userName="lisi";



        //参数判断
        if (bp.getOrderId() == null || bp.getPwd() == null)
            throw new MyException(FundExceptionCode.PARAM_NULL.getCode(), FundExceptionCode.PARAM_NULL.getMsg());
        //订单前置判断
        //根据订单id 查到订单对象 订单对象
        //订单是否存在
        Result<ClassesOrderDto> corder = coc.getClassesOrderById(bp.getOrderId());
        ClassesOrderDto co = corder.getData();
        if(co==null)
            throw new MyException(FundExceptionCode.ORDER_NULL.getCode(),FundExceptionCode.ORDER_NULL.getMsg());
        if(co.getState()!=4)
        throw new MyException(FundExceptionCode.CANNOT_PAY.getCode(),FundExceptionCode.CANNOT_PAY.getMsg());
        String s2 = srt.opsForValue().get("PayingOrderNum:" + corder.getData().getOrderNum());
        if(s2!=null)
            throw new MyException(FundExceptionCode.PAYING_ORDER.getCode(),FundExceptionCode.PAYING_ORDER.getMsg());
        String s3 = srt.opsForValue().get("trade_done" + co.getOrderNum());
        if(s3!=null)
            throw new MyException(FundExceptionCode.PAYING_DONE.getCode(),FundExceptionCode.PAYING_DONE.getMsg());
        //订单是否存在
        if (corder.getData() == null)
            throw new MyException(FundExceptionCode.PARAM_NULL.getCode(), FundExceptionCode.PARAM_NULL.getMsg());
        //订单是否已支付
        if (corder.getData().getState()==1)
            throw new MyException(FundExceptionCode.REPEAT_PAY_ERROR.getCode(), FundExceptionCode.REPEAT_PAY_ERROR.getMsg());
        String s = srt.opsForValue().get("PayingOrderNum:"+corder.getData().getOrderNum());
        if(s!=null)
            throw new MyException(FundExceptionCode.ORDER_IS_PAYING.getCode(),FundExceptionCode.ORDER_IS_PAYING.getMsg());
        String s1 = srt.opsForValue().get("trade_done" + co.getOrderNum());
        if(s1!=null)
            throw new MyException(FundExceptionCode.REPEAT_PAY_ERROR.getCode(),FundExceptionCode.REPEAT_PAY_ERROR.getMsg());

        //查找收支方信息 是否存在该用户
        Result<Integer> sid = sc.findAccountIdByStudentId(co.getStudentId());
        Integer data = sid.getData();
        if(data.intValue()!=uid.intValue())
            throw new MyException(FundExceptionCode.NOT_THIS_STUDENT.getCode(), FundExceptionCode.NOT_THIS_STUDENT.getMsg());
        if(sid.getData().intValue()!=uid)
            throw new MyException(FundExceptionCode.NOT_STU_ORDER.getCode(), FundExceptionCode.NOT_STU_ORDER.getMsg());

        Result<Integer> vid = vc.findAccountIdByVenueId(co.getVenueId());
        if(vid.getCode()==null)
            throw new MyException(FundExceptionCode.NOT_THIS_VENUE.getCode(), FundExceptionCode.NOT_THIS_VENUE.getMsg());

        srt.opsForValue().set("PayingOrderNum:"+corder.getData().getOrderNum(),"paying",10, TimeUnit.SECONDS);

        //记录
        //根据学员id 教练id 课程金额 更改用户余额 pwd也得传输
        //注意判断学员余额！如果余额不足 返回错误编号6005
        PayRecord payRecord = new PayRecord();
        payRecord.setScence(SchemaCode.PAY_CODE.getNum());
        payRecord.setScenceId(co.getId());
        payRecord.setPaymentWay(PaymentRelated.BALANCE_NAME.getDesc());
        payRecord.setCashAmount(co.getPrice());
        payRecord.setState(0);
        String payNum = CommonUtil.getRechargeCode(SchemaCode.SERIAL_CODE.getNum());
        payRecord.setPayNum(payNum);
        payRecord.setOrderNum(co.getOrderNum());
        payRecordService.save(payRecord);



        //支付接口
        ChangeAccountMoneyInfo changeAccountMoneyInfo = new ChangeAccountMoneyInfo();
        //支付方
        changeAccountMoneyInfo.setDudId(sid.getData());
        changeAccountMoneyInfo.setDudpassword(bp.getPwd());
        //收款方
        changeAccountMoneyInfo.setAddId(vid.getData());
        changeAccountMoneyInfo.setMoneyAmount(co.getPrice());
        //执行
        Result result = userClient.changeMoneyByAccountId(changeAccountMoneyInfo);
        if(result.getCode()!=200)
            throw new MyException(FundExceptionCode.TRADE_FAIL.getCode(),FundExceptionCode.TRADE_FAIL.getMsg());
        srt.opsForValue().set("trade_done"+co.getOrderNum(),"tradeDone");
        //支付成功


        //异步回调根据订单id 更改订单状态为已支付 添加支付表和流水表数据 成功第二次
        RechargeStateInfo msg = new RechargeStateInfo();
        msg.setSericalNum(payNum);
        String orderNum = CommonUtil.getRechargeCode(SchemaCode.PAY_CODE.getNum());
        msg.setOut_trade_no(orderNum);
        msg.setScence(SchemaCode.PAY_CODE.getNum());
        msg.setScenceId(co.getId());
        msg.setPayment(PaymentRelated.BALANCE_NAME.getDesc());
        msg.setCashAmount(co.getPrice());
        msg.setState(1);//已支付
        //根据订单 获取收钱人 id name
        msg.setPayerId(uid);
        msg.setPayeeId(vid.getData());
        msg.setPayeeName(co.getVenueName() + ":" + co.getCoachName());
        msg.setPayerName(co.getStudentName());

        Message<RechargeStateInfo> info = MessageBuilder.withPayload(msg)
                .build();
        rt.asyncSend("msgsend:add_info", info,
                new SendCallback() {
                    @Override
                    public void onSuccess(SendResult sendResult) {
                        System.out.println("发送成功: " + sendResult);
                    }

                    @Override
                    public void onException(Throwable e) {
                        System.out.println("发送失败: " + e.getMessage());
                    }
                });

        //添加参数到BalancePayDto 返回前端 不用等更改订单状态成功
        BalancePayDto balancePayDto = new BalancePayDto();
        balancePayDto.setCashAmount(co.getPrice());
        balancePayDto.setOrderNum(orderNum);
        balancePayDto.setCreateTime(LocalDateTime.now());
        balancePayDto.setVenueName(co.getVenueName());
        balancePayDto.setCoachName(co.getCoachName());
        return new Result<BalancePayDto>().setCode(200).setMsg("余额支付成功").setData(balancePayDto);
    }

    @Override
    public Result addPayRecord(PayRecordInfo payRecord) {
        PayRecord payRecord1 = BeanCopyUtil.copyObject(payRecord, PayRecord.class);
        payRecord1.setPayNum(CommonUtil.getRechargeCode(SchemaCode.SERIAL_CODE.getNum()));
        if (payRecordService.save(payRecord1))
            new Result().setCode(200).setMsg("更新支付表成功");
        throw new MyException(FundExceptionCode.DAO_ERROR.getCode(), FundExceptionCode.DAO_ERROR.getMsg());
    }

    @Override
    public Result<Page<PayRecordToShow>> payRecord(PayRecordForm payRecordForm) {
        //日期是否为空 end为空的话 默认到现在 start为空 默认 现在时间到半年前
        //start
        if(payRecordForm.getStartDate()==null){
            //半年前的现在
            payRecordForm.setStartDate(DateUtil
                    .timeFormatString(
                            (System.currentTimeMillis() - 15811200000l), "yyyy-MM-dd HH:mm:ss"));
        }

        if(payRecordForm.getEndDate()==null){
            //半年前的现在
            payRecordForm.setEndDate(DateUtil
                    .timeFormatString(
                            System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
        }
        SPayRecordForm searchh = BeanCopyUtil.copyObject(payRecordForm, SPayRecordForm.class);
        searchh.setStart(CommonUtil.transStrToLocalDateTime(payRecordForm.getStartDate()));
        searchh.setEnd(CommonUtil.transStrToLocalDateTime(payRecordForm.getEndDate()));
        if(searchh.getEnd().compareTo(searchh.getStart())<0) throw new MyException(FundExceptionCode.DATE_ERROR.getCode(),FundExceptionCode.DATE_ERROR.getMsg());

        return new Result<Page<PayRecordToShow>>().setCode(200).setMsg("交易记录").setData(BeanCopyUtil.copyPage(payRecordService.getPayRecord(searchh),PayRecordToShow.class));
    }

    @Override
    public Result<Page<MyWalletToShow>> myWallet(MyWalletForm myWalletForm) {
        //日期是否为空 end为空的话 默认到现在 start为空 默认 现在时间到半年前
        //start
        if(myWalletForm.getStartDate()==null){
            //半年前的现在
            myWalletForm.setStartDate(DateUtil
                    .timeFormatString(
                            (System.currentTimeMillis() - 15811200000l), "yyyy-MM-dd HH:mm:ss"));
        }
        if(myWalletForm.getEndDate()==null){
            //半年前的现在
            myWalletForm.setEndDate(DateUtil
                    .timeFormatString(
                            System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"));
        }
        //前台帐户id
        //Integer uid = userDto.getId().intValue();
        Integer uid = 1;
        //前台帐户用户名
        //String userName = userDto.getUserName();
        String uName = "李四";
        MyWalletDto myWallet = BeanCopyUtil.copyObject(myWalletForm, MyWalletDto.class);
        myWallet.setUserId(uid);
        myWallet.setStart(CommonUtil.transStrToLocalDateTime(myWalletForm.getStartDate()));
        myWallet.setEnd(CommonUtil.transStrToLocalDateTime (myWalletForm.getEndDate()));
        if(myWallet.getEnd().compareTo(myWallet.getStart())<0) throw new MyException(FundExceptionCode.DATE_ERROR.getCode(),FundExceptionCode.DATE_ERROR.getMsg());
        return new Result<Page<MyWalletToShow>>().setCode(200).setMsg("我的钱包记录").setData(BeanCopyUtil.copyPage(payRecordService.myWalletInfo(myWallet),MyWalletToShow.class));
    }
}
